package com.rds.common.utils.file;

import com.alibaba.fastjson2.JSONObject;
import com.amazonaws.*;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.rds.common.constant.S3Constants;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;


/**
 * 文件上传工具类
 *
 * @author rds
 */
public class FileS3UploadUtils
{
    /*private final static String server_url_port = "10.192.32.101:8060";
    //private final static String server_port = "8060";
    private final static String access_key = "8GGUVVJLKPIE768R7D7N";
    private final static String secret_key = "Yu9fNxaTI6MKDOdrkEPnag8d3MxQBlNwSaFChE15";
    private final static String user = "test";

    private final static String server_url_port = "obs.sunnyoptical.cn:8060";
    //private static String server_port = "8060";
    private final static String access_key = "I2BJS8D0DF0AKU8MRHG3";
    private final static String secret_key = "Hol5mN8yc3sg2B132pL2AoEJoW2TEQA0VZpc99He";
    private final static String user = "plm";*/
    public static AWSCredentials credentials = new BasicAWSCredentials(S3Constants.ACCESS_KEY, S3Constants.SECRET_KEY);
    public static AmazonS3 client = null;

    // 上传
    public static PutObjectResult putObject(String bucketName, String key, File file) {
        createClient();

        PutObjectResult putResult = null;
        //创建用户自定义元数据
        ObjectMetadata metadata = new ObjectMetadata();
        //metadata.addUserMetadata("Use", "test");
        metadata.addUserMetadata("Use", S3Constants.S3_USER);
        //创建上传文件请求（PutObjectRequest）
        PutObjectRequest putRequest = new PutObjectRequest(bucketName, key, file);
        putRequest.setMetadata(metadata);
        try {
            //调用putObject上传文件
            putResult = client.putObject(putRequest);
        } catch (AmazonServiceException ase) {
            System.out.println("Caught an AmazonServiceException when put object of\"" + key + "\".");
            System.out.println("Error Message: " + ase.getMessage());
            System.out.println("HTTP Status Code: " + ase.getStatusCode());
            System.out.println("AWS Error Code: " + ase.getErrorCode());
            System.out.println("Error Type: " + ase.getErrorType());
            System.out.println("Request ID: " + ase.getRequestId());
            System.exit(1);
        }
        return putResult;
    }

    public static void multiPutObject(AmazonS3 client, String bucketName, String key, File file){
        InitiateMultipartUploadRequest initRequest = new
                InitiateMultipartUploadRequest(bucketName, key);
        InitiateMultipartUploadResult initResult = null;
        //创建分段上传
        try {
            initResult = client.initiateMultipartUpload(initRequest);
        }catch(AmazonServiceException ase) {
            System.out.println("Caught an AmazonServiceException when create MultipartUpload of \""+key+"\".");
            System.out.println("Error Message: " + ase.getMessage());
            System.out.println("HTTP Status Code: " + ase.getStatusCode());
            System.out.println("AWS Error Code: " + ase.getErrorCode());
            System.out.println("Error Type: " + ase.getErrorType());
            System.out.println("Request ID: " + ase.getRequestId());
            System.exit(1);
        }
        long fileLength = file.length();
        long partSize = 5 * 1024 * 1024;//5M
        long filePosition = 0;
        List<PartETag> partETags = new ArrayList<PartETag>();
        UploadPartRequest upRequest = new UploadPartRequest();
        upRequest.setBucketName(bucketName);
        upRequest.setKey(key);
        upRequest.setFile(file);
        upRequest.setUploadId(initResult.getUploadId());
        //上传文件
        for(int i = 1; filePosition < fileLength; i++){
            partSize = Math.min(partSize, (fileLength - filePosition));
            upRequest.setPartNumber(i);
            upRequest.setFileOffset(filePosition);
            upRequest.setPartSize(partSize);
            try {
                UploadPartResult uploadResult = client.uploadPart(upRequest);
                partETags.add(uploadResult.getPartETag());
            }catch(AmazonServiceException ase) {
                System.out.println("Caught an AmazonServiceException when upload part of \""+key+"\".");
                System.out.println("Error Message: " + ase.getMessage());
                System.out.println("HTTP Status Code: " + ase.getStatusCode());
                System.out.println("AWS Error Code: " + ase.getErrorCode());
                System.out.println("Error Type: " + ase.getErrorType());
                System.out.println("Request ID: " + ase.getRequestId());
                System.exit(1);
            }
            filePosition += partSize;
        }
        //完成分段上传
        System.out.println(bucketName);
        System.out.println(key);
        System.out.println(initResult.getUploadId());
        for(PartETag tag:partETags) {
            System.out.println(tag.getETag());
        }
        CompleteMultipartUploadRequest compRequest = new
                CompleteMultipartUploadRequest(bucketName, key, initResult.getUploadId(), partETags);
        try {
            client.completeMultipartUpload(compRequest);
        }catch(AmazonServiceException ase) {
            System.out.println("Caught an AmazonServiceException when finish MultipartUpload of \""+key+"\".");
            System.out.println("Error Message: " + ase.getMessage());
            System.out.println("HTTP Status Code: " + ase.getStatusCode());
            System.out.println("AWS Error Code: " + ase.getErrorCode());
            System.out.println("Error Type: " + ase.getErrorType());
            System.out.println("Request ID: " + ase.getRequestId());
            System.exit(1);
        }
    }

    //
    public static String testViewURL(String bucketName,String objectKey) {
        try {
            createClient();
            // 设置URL有效时间为1h
            java.util.Date expiration = new java.util.Date();
            long expTimeMillis = expiration.getTime();
            expTimeMillis += 1000 * 60 * 10;
            expiration.setTime(expTimeMillis);
            // 生成URL
            System.out.println("Generating pre-signed URL.");
            GeneratePresignedUrlRequest generatePresignedUrlRequest =
                    new GeneratePresignedUrlRequest(bucketName, objectKey)
                            .withMethod(HttpMethod.GET)
                            .withExpiration(expiration);
            URL url = client.generatePresignedUrl(generatePresignedUrlRequest);
            System.out.println("Pre-Signed URL: " + url.toString());
            return url.toString();
        }catch(AmazonServiceException e) {
            e.printStackTrace();
        }catch(SdkClientException e) {
            e.printStackTrace();
        }
        return "";
    }

    //下载
    public static void getObject(String bucketName, String key, String filePath){

        ObjectMetadata objectMetadata = null;
        try {
            createClient();
            new File(filePath).mkdirs();
            File file = new File(filePath+key);
            if(!file.exists()){
                file.createNewFile();
            }
            objectMetadata = client.getObject(new GetObjectRequest(bucketName, key), file);
            System.out.println(JSONObject.toJSONString(objectMetadata));
        } catch (Exception e){
            System.out.println(e.getMessage());
        }

    }

    public static S3Object getObject(String bucketName, String key){
        S3Object fullObject = null, objectPortion = null, headerOverrideObject = null;
        try {
            createClient();
            fullObject = client.getObject(new GetObjectRequest(bucketName, key));
            //获取系统元数据
            System.out.println("Content-Type: " + fullObject.getObjectMetadata().getContentType());
            displayTextInputStream(fullObject.getObjectContent());
            // 下载指定范围的对象
            GetObjectRequest rangeObjectRequest = new GetObjectRequest(bucketName, key);
            objectPortion = client.getObject(rangeObjectRequest);
            System.out.println("Printing bytes retrieved.");
            displayTextInputStream(objectPortion.getObjectContent());
            //重写相应header内容，然后获取整个对象
            ResponseHeaderOverrides headerOverrides = new ResponseHeaderOverrides()
                    .withCacheControl("No-cache")
                    .withContentDisposition("attachment; filename=example.docx");
            GetObjectRequest getObjectRequestHeaderOverride = new GetObjectRequest(bucketName, key).withResponseHeaders(headerOverrides);
            headerOverrideObject = client.getObject(getObjectRequestHeaderOverride);
            displayTextInputStream(headerOverrideObject.getObjectContent());
        } catch (Exception e){
            System.out.println(e.getMessage());
        }
        return fullObject;
    }


    // S3文件删除
    public static int deleteObject(String bucketName, String key) {
//        DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName);
//        deleteRequest.withKeys(key);
        try {
            createClient();
            client.deleteObject(new DeleteObjectRequest(bucketName, key));
            return 1;
        }catch(AmazonServiceException ase) {
            System.out.println("Error Message: " + ase.getMessage());
            System.out.println("HTTP Status Code: " + ase.getStatusCode());
            System.out.println("AWS Error Code: " + ase.getErrorCode());
            System.out.println("Error Type: " + ase.getErrorType());
            System.out.println("Request ID: " + ase.getRequestId());
            return 0;
        }
    }

    private static void displayTextInputStream(InputStream input) throws IOException {
        // Read the text input stream one line at a time and display each line.
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        String line = null;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        System.out.println();
    }

    public static void createClient(){
        ClientConfiguration config = new ClientConfiguration();
        config.setProtocol(Protocol.HTTP);
        config.setConnectionTimeout(30000);
        config.setUseExpectContinue(true);
        AwsClientBuilder.EndpointConfiguration end_point = null;
        end_point = new AwsClientBuilder.EndpointConfiguration(S3Constants.SERVER_URL_PORT, "");
        client = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withClientConfiguration(config)
                .withEndpointConfiguration(end_point)
                .withPathStyleAccessEnabled(true)
                .build();
    }

    // 创建桶
    public static Bucket creatingBucket(String bucketName) {
        Bucket bucket = null;
        try {
            bucket = client.createBucket(bucketName);
        } catch (AmazonServiceException ase) {
            System.out.println("Caught an AmazonServiceException when create\"" + bucketName + "\".");
            System.out.println("Error Message: " + ase.getMessage());
            System.out.println("HTTP Status Code: " + ase.getStatusCode());
            System.out.println("AWS Error Code: " + ase.getErrorCode());
            System.out.println("Error Type: " + ase.getErrorType());
            System.out.println("Request ID: " + ase.getRequestId());
        }
        return bucket;
    }
}
